package handlers

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/jmoiron/sqlx"
	"learning/gooop/saga/mqs/database"
	"learning/gooop/saga/mqs/eventbus"
	"learning/gooop/saga/mqs/logger"
	"learning/gooop/saga/mqs/models"
	"learning/gooop/saga/mqs/models/events"
	"net/http"
)

func Subscribe(c *gin.Context) {
	// parse request
	msg := &models.SubscribeMsg{}
	if err := c.ShouldBindBodyWith(&msg, binding.JSON); err != nil {
		c.AbortWithStatusJSON(
			http.StatusInternalServerError,
			gin.H{ "ok": false, "error": err.Error()})
		return
	}

	// fixme: validate msg

	// save to db
	logger.Logf("handlers.Subscribe, msg=%v", msg)
	err := database.DB(func(db *sqlx.DB) error {
		r,e := db.Exec(
			"insert or ignore into subscriber(ClientID, topic, NotifyURL, ExpireTime) values(?, ?, ?, ?)",
			msg.ClientID,
			msg.Topic,
			msg.NotifyUrl,
			msg.ExpireTime)
		if e != nil {
			return e
		}

		rows, e := r.RowsAffected()
		if e != nil {
			return e
		}

		if rows == 0 {
			// already exists (client_id, topic)
			_, e = db.Exec("update subscriber set ExpireTime=? where ClientID=? and topic=?", msg.ExpireTime, msg.ClientID, msg.Topic)
			if e != nil {
				return e
			}
		}

		return nil
	})

	// reply
	if err != nil {
		logger.Logf("handlers.Subscribe, err=%v", err)
		c.JSON(http.StatusInternalServerError, gin.H{ "ok": false, "error": err.Error()})

	} else {
		c.JSON(http.StatusOK, gin.H { "ok": true })

		logger.Logf("handlers.Subscribe, event=%s, msg=%v", events.SubscriberRegisteredEvent, msg)
		eventbus.GlobalEventBus.Pub(events.SubscriberRegisteredEvent, msg)
	}
}